#ifndef __M_CONNECTION_H__
#define __M_CONNECTION_H__
#include "channel.hpp"

namespace zhong
{
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>;

        Connection(const ConsumerManager::ptr &consumer_manager,
                   const VirtualHostManager::ptr &host_manager,
                   const UserManager::ptr &user_manager,
                   const ProtobufCodecPtr &codec,
                   const muduo::net::TcpConnectionPtr &conn,
                   const threadpool::ptr &pool)
            : _consumer_manager(consumer_manager),
              _host_manager(host_manager),
              _user_manager(user_manager),
              _codec(codec),
              _connection(conn),
              _pool(pool),
              _channel_manager(std::make_shared<ChannelManager>()) {}

        // 信道的打开和关闭
        void openChannel(const openChannelRequestPtr &ptr)
        {
            bool ret = _channel_manager->openChannel(ptr->channel_id(), _host_manager, _consumer_manager, _user_manager, _codec, _connection, _pool);
            if (ret == false)
            {
                DEBUG_LOG("创建信道失败，信道ID重复");
                return sendBasicResponse(ptr->request_id(), ptr->channel_id(), false);
            }

            return sendBasicResponse(ptr->request_id(), ptr->channel_id(), true);
        }
        void closeChannel(const closeChannelRequestPtr &ptr)
        {
            _channel_manager->closeChannel(ptr->channel_id());
            sendBasicResponse(ptr->request_id(), ptr->channel_id(), true);
        }

        Channel::ptr getChannel(const std::string &channel_id)
        {
            return _channel_manager->getChannel(channel_id);
        }

    private:
        void sendBasicResponse(const std::string &request_id, const std::string &channel_id, bool ok)
        {
            // 发送响应
            basicResponse response;
            response.set_request_id(request_id);
            response.set_channel_id(channel_id);
            response.set_ok(ok);
            // 发送操作结果
            _codec->send(_connection, response);
        }

    private:
        muduo::net::TcpConnectionPtr _connection; // 信道关联的TCP链接
        ProtobufCodecPtr _codec;                  // 协议处理句柄
        ConsumerManager::ptr _consumer_manager;    // 消费者管理句柄
        VirtualHostManager::ptr _host_manager;    // 虚拟机管理句柄
        UserManager::ptr _user_manager;
        threadpool::ptr _pool;                // 线程池句柄
        ChannelManager::ptr _channel_manager; // 信道管理句柄
    };

    class ConnectionManager
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>;

        ConnectionManager() {}

        void createConnection(const ConsumerManager::ptr &consumer_manager,
                              const VirtualHostManager::ptr &host_manager,
                              const UserManager::ptr user_manager,
                              const ProtobufCodecPtr &codec,
                              const muduo::net::TcpConnectionPtr &conn,
                              const threadpool::ptr &pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connections.find(conn);
            if (it != _connections.end())
            {
                return;
            }
            Connection::ptr connection = std::make_shared<Connection>(consumer_manager, host_manager, user_manager, codec, conn, pool);
            _connections.insert(std::make_pair(conn, connection));
        }
        void deleteConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _connections.erase(conn);
        }
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connections.find(conn);
            if (it == _connections.end())
            {
                return Connection::ptr();
            }
            return it->second;
        }

    private:
        std::mutex _mutex;
        // connections的kv结构为：当前的Tcp链接的指针 管理信道的链接指针
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _connections;
    };
};

#endif